package com.zb.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zb.constant.NetworkConstant;
import com.zb.constant.StoreConstant;
import com.zb.constant.WorkConstant;
import com.zb.entity.*;
import com.zb.excel.converter.WorkConverter;
import com.zb.order.service.ConWorkSpareService;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.service.impl.WorkServiceLog;
import com.zb.store.service.ConStoreInboundService;
import com.zb.store.service.ConStoreOutboundService;
import com.zb.utils.ZbOrderNoUtil;
import com.zb.view.*;
import com.zb.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author WEN
 * @Date 2023/10/26 0026
 **/
@Service
public class ConWorkSpareServiceImpl implements ConWorkSpareService {
    @Resource
    private ZjWorkOrderService workOrderService;
    @Resource
    private ZjNetworkService networkService;
    @Resource
    private ZjUserService userService;
    @Resource
    private ZjWorkSpareService workSpareService;
    @Resource
    private ViewNetworkEmpDetailService viewNetworkEmpDetailService;
    @Resource
    private ZjWorkSpareReceiptService workSpareReceiptService;
    @Resource
    private ZjWorkSpareMaterialService workSpareMaterialService;
    @Resource
    private ZjWorkSpareMaterialApplyService workSpareMaterialApplyService;
    @Resource
    private ViewGoodsService viewGoodsService;
    @Resource
    private ZjWorkSpareReturnService workSpareReturnService;
    @Resource
    private ZjWorkSpareReturnReceiptSendService workSpareReturnReceiptSendService;
    @Resource
    private ZjStoreService storeService;
    @Resource
    private ZjWorkSpareMaterialAnnexService workSpareMaterialAnnexService;
    @Resource
    private ViewStoreStoreGoodsStockService viewStoreStoreGoodsStockService;
    @Resource
    private ZjStorePositionService storePositionService;
    @Resource
    private ConStoreOutboundService conStoreOutboundService;
    @Resource
    private ConStoreInboundService conStoreInboundService;
    @Resource
    private ZjStoreTypeService storeTypeService;
    @Resource
    private ZjFactoryService factoryService;
    @Resource
    private ZjWorkDetailService workDetailService;
    @Resource
    private ZjFactoryAccountBalanceService factoryAccountBalanceService;


    // 保存或修改工单备件
    @Override
    @Transactional
    public void save(AccounLoginInfo loginInfo, WorkSpareVo workSpareVo) {
        ZjWorkOrder workOrder = workOrderService.getById(workSpareVo.getWorkId());
        Assert.isTrue(null != workOrder, "工单ID参数["+ workSpareVo.getWorkId() +"]的工单数据不存在");
        Assert.isTrue(workOrder.getStatus() == WorkConstant.WORK_STATUS_3, "工单单号["+ workOrder.getCode() +"]流程状态处于非[处理中]状态，不可跨流程或重复操作该工单");
        if (workSpareVo.getReceiptAddrType() == 1) {
            Assert.isTrue(null != userService.getById(workSpareVo.getUserOrNetworkId()), "地址类型的工单客户ID参数["+ workSpareVo.getUserOrNetworkId() +"]的客户数据不存在系统中");
        }
        if (workSpareVo.getReceiptAddrType() == 2) {
            Assert.isTrue(null != networkService.getById(workSpareVo.getUserOrNetworkId()), "地址类型的服务商ID参数["+ workSpareVo.getUserOrNetworkId() +"]的客户数据不存在系统中");
        }
        ZjWorkSpare spare = new ZjWorkSpare();
        BeanUtil.copyProperties(workSpareVo, spare);
        spare.setApplyRemark(workSpareVo.getRemark());

        WorkLogVo logVo = null;
        if (null != spare.getId()) {
            workSpareService.updateById(spare);
            logVo = new WorkLogVo(loginInfo, workSpareVo.getWorkId(), "客服修改申请工单备件", "工单客服["+ loginInfo.getName() +"]修改工单备件，等待审核");
        } else {
            ViewNetworkEmpDetail empDetailView = viewNetworkEmpDetailService.getManagerByNetworkId(workOrder.getNetworkId());
            ZjNetwork network = networkService.getById(workOrder.getNetworkId());

            spare.setId(IdWorker.getId());
            spare.setCustAccId(loginInfo.getCustAccId());
            spare.setWorkNo(workOrder.getCode());
            spare.setStatus(WorkConstant.WORK_SPARE_STATUS_1);
            spare.setCode(ZbOrderNoUtil.orderSpareNo(loginInfo.getCustAccId()));
            spare.setNetworkId(workOrder.getNetworkId());
            spare.setNetworkManagerEmpId(empDetailView.getId());
            spare.setNetworkEngineerEmpId(workOrder.getNetworkEmpId());
            spare.setApplyEmpType(WorkConstant.APPLY_OR_CHECK_EMP_TYPE_1);
            spare.setApplyEmpId(loginInfo.getId());
            spare.setApplyEmp(loginInfo.getName());
            spare.setReceived(network.getCategory() != NetworkConstant.CATEGORY_2);
            spare.setOldCopeWay(0);
            spare.setReviewEmpId(0L);
            spare.setReviewEmp("");
            spare.setReviewRemark("");
            workSpareService.save(spare);
            ZjWorkDetail detail = new ZjWorkDetail();
            detail.setId(workOrder.getId());
            detail.setNoReviewApplyWorkSpareNum(1);
            workDetailService.updateOrderEventById(detail);
            StringBuilder builder = new StringBuilder("工单客服[").append(loginInfo.getName());
            builder.append("]新增工单备件，申请类型：").append(WorkConverter.getWorkSpareApplyType(workSpareVo.getType(), workSpareVo.getNetworkSpareType())).append("，等待审核");
            logVo = new WorkLogVo(loginInfo, workSpareVo.getWorkId(), "客服新增申请工单备件", builder.toString());
        }
        workSpareReceiptService.save(loginInfo.getCustAccId(), spare.getId(), workSpareVo);
        workSpareMaterialService.save(loginInfo.getCustAccId(), workOrder.getId(), spare.getId(), workSpareVo.getSpareMaterialVos(), workSpareVo.getDelSpareMaterialIds());
        workOrderService.updateNewAdvanceOrWaitCopeEventById(workOrder.getId(), workOrder.getNewAdvance(), workOrder.getWaitCopeEvent() +1);

        WorkServiceLog.saveService(logVo);
        WorkServiceLog.saveServiceWorkSpareLog(new WorkSpareLogVo(loginInfo, workSpareVo.getWorkId(), spare.getId(), logVo.getEvent(), logVo.getContent()));
    }

    // 获取工单备件列表
    @Override
    public Map<String, Object> getList(Long custAccId, WorkSpareSelectVo selectVo) {
        PageUtil.setPageLimit(selectVo);
        long count = workSpareService.getListCount(custAccId, selectVo);
        if (count <= 0) {
            return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, new ArrayList<>());
        }
        List<ZjWorkSpare> workSpareList = workSpareService.getList(custAccId, selectVo);
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, getSpareListVos(workSpareList));
    }

    // 根据工单ID获取工单详情的工单备件列表
    @Override
    public Map<String, Object> getOrderDetailWorkSpareList(Long workId, PageUtil pageUtil) {
        PageUtil.setPageLimit(pageUtil);
        long count = workSpareService.getOrderDetailWorkSpareListCount(workId);
        if (count <= 0) {
            return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, new ArrayList<>());
        }
        List<ZjWorkSpare> workSpareList = workSpareService.getOrderDetailWorkSpareList(workId, pageUtil);
        List<Long> workSpareIds = workSpareList.stream().map(ZjWorkSpare::getId).toList();
        List<ZjWorkSpareMaterial> spareMaterialList = workSpareMaterialService.getByWorkSpareIds(workSpareIds);
        List<Long> spareIds = spareMaterialList.stream().filter(f -> null != f.getSpareId() && 0 != f.getSpareId()).map(ZjWorkSpareMaterial::getSpareId).distinct().toList();
        List<Long> spareSpecIds = spareMaterialList.stream().filter(f -> null != f.getSpecId() && 0 != f.getSpecId()).map(ZjWorkSpareMaterial::getSpecId).distinct().toList();
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(spareIds, spareSpecIds);
        List<ZjWorkSpareMaterialApply> materialApplyList = new ArrayList<>();
        List<Long> ids = spareMaterialList.stream().map(ZjWorkSpareMaterial::getId).toList();
        if (CollectionUtil.isNotEmpty(ids)) {
            materialApplyList.addAll(workSpareMaterialApplyService.listByIds(ids));
        }
        List<OrderDetailWorkSpareListVo> voList = workSpareList.stream().map(spare -> {
            return getSpareListVo(spareMaterialList, viewGoodsList, materialApplyList, spare);
        }).toList();
        return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, voList);
    }
    // 根据工单ID获取工单详情的工单备件列表
    @Override
    public List<OrderDetailWorkSpareListVo> getOrderDetailWorkSpareList(Long workId) {
        // 获取工单备件列表
        List<ZjWorkSpare> workSpareList = workSpareService.getOrderDetailWorkSpareList(workId);
        if (workSpareList.isEmpty()) {
            return new ArrayList<>();  // 如果没有符合条件的数据，返回空列表
        }

        // 获取工单备件ID列表
        List<Long> workSpareIds = workSpareList.stream().map(ZjWorkSpare::getId).toList();
        List<ZjWorkSpareMaterial> spareMaterialList = workSpareMaterialService.getByWorkSpareIds(workSpareIds);

        // 获取备件和规格ID列表
        List<Long> spareIds = spareMaterialList.stream().filter(f -> f.getSpareId() != null && f.getSpareId() != 0).map(ZjWorkSpareMaterial::getSpareId).distinct().toList();
        List<Long> spareSpecIds = spareMaterialList.stream().filter(f -> f.getSpecId() != null && f.getSpecId() != 0).map(ZjWorkSpareMaterial::getSpecId).distinct().toList();

        // 获取商品信息
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(spareIds, spareSpecIds);

        // 获取备件材料申请列表
        List<ZjWorkSpareMaterialApply> materialApplyList = new ArrayList<>();
        List<Long> ids = spareMaterialList.stream().map(ZjWorkSpareMaterial::getId).toList();
        if (!ids.isEmpty()) {
            materialApplyList.addAll(workSpareMaterialApplyService.listByIds(ids));
        }

        // 构建返回的 VO 列表
        List<OrderDetailWorkSpareListVo> voList = workSpareList.stream().map(spare -> {
            return getSpareListVo(spareMaterialList, viewGoodsList, materialApplyList, spare);
        }).toList();

        return voList;  // 直接返回 List<OrderDetailWorkSpareListVo>
    }

    // 根据工单备件ID获取工单备件详情
    @Override
    public WorkSpareDetailVo getDetail(Long id) {
        ZjWorkSpare workSpare = workSpareService.getById(id);
        Assert.isTrue(null != workSpare, "工单备件ID参数["+ id +"]的数据不存在");

        WorkSpareDetailInfoVo vo = new WorkSpareDetailInfoVo();
        BeanUtil.copyProperties(workSpareService.getBeforeCheckOrderSpareDetail(id), vo);
        if (workSpare.getOldCopeWay() == 2) {
            ZjWorkSpareReturn spareReturn = workSpareReturnService.getById(id);
            if (null != spareReturn) {
                ZjStore store = storeService.getById(spareReturn.getStoreId());
                vo.setStore(null != store ? store.getName() : "");
                ZjWorkSpareReturnReceiptSend receiptSend = workSpareReturnReceiptSendService.getById(spareReturn.getId());
                vo.setOldReceiptName(receiptSend.getReceiptName());
                vo.setOldReceiptPhone(receiptSend.getReceiptPhone());
                vo.setOldReceiptProvince(receiptSend.getReceiptProvince());
                vo.setOldReceiptCity(receiptSend.getReceiptCity());
                vo.setOldReceiptArea(receiptSend.getReceiptArea());
                vo.setOldReceiptTown(receiptSend.getReceiptTown());
                vo.setOldReceiptAddress(receiptSend.getReceiptAddress());
            }
        }
        return vo;
    }

    // 根据工单备件ID获取工单备件详情的物料信息
    @Override
    public List<WorkSpareDetailMaterialVo> getOrderSpareMaterial(Long workSpareId) {
        QueryWrapper<ZjWorkSpareMaterial> wrapper = new QueryWrapper<>();
        wrapper.select("id", "work_id", "work_spare_id", "status", "type", "spare_id", "spec_id", "qty", "price", "pay_network_price", "receive_factory_price", "store_id",
                "is_overinsured AS overinsured", "sure_use_status", "remark");
        wrapper.eq("work_spare_id", workSpareId);
        List<ZjWorkSpareMaterial> materialList = workSpareMaterialService.list(wrapper);
        if (CollectionUtil.isEmpty(materialList)) {
            return new ArrayList<>();
        }
        List<Long> ids = materialList.stream().map(ZjWorkSpareMaterial::getId).toList();
        List<Long> spareIds = materialList.stream().filter(f -> null != f.getSpareId() && f.getSpareId() != 0).map(ZjWorkSpareMaterial::getSpareId).distinct().toList();
        List<Long> specIds = materialList.stream().filter(f -> null != f.getSpecId() && f.getSpecId() != 0).map(ZjWorkSpareMaterial::getSpecId).distinct().toList();
        List<Long> storeIds = materialList.stream().map(ZjWorkSpareMaterial::getStoreId).distinct().toList();
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(spareIds, specIds);
        List<ZjWorkSpareMaterialAnnex> annexes =  workSpareMaterialAnnexService.getByWorkSpareMaterialIds(ids);
        List<ZjWorkSpareMaterialApply> applyList = workSpareMaterialApplyService.listByIds(ids);
        List<ZjStore> storeList = storeService.listByIds(storeIds);
        return materialList.stream().map(spare -> {
            WorkSpareDetailMaterialVo vo = new WorkSpareDetailMaterialVo();
            BeanUtil.copyProperties(spare, vo);
            vo.setImages(annexes.stream().filter(f -> Objects.equals(f.getWorkSpareMaterialId(), spare.getId())).map(an -> {
                return new OrderImageVo(an.getId(), an.getImage());
            }).toList());
            ZjWorkSpareMaterialApply apply = applyList.stream().filter(f -> Objects.equals(f.getId(), spare.getId())).findFirst().orElse(null);
            vo.setApplySpareModel(apply.getModel());
            vo.setApplySpareSpec(apply.getSpec());
            vo.setApplySpareSpecCode(apply.getSpecSku());
            if (spare.getStatus() == 2) {
                viewGoodsList.stream().filter(f -> Objects.equals(f.getId(), spare.getSpareId()) && Objects.equals(f.getSpecId(), spare.getSpecId())).findFirst().ifPresent(specView -> {
                    vo.setCheckSpareModel(specView.getModel());
                    vo.setCheckSpareSpec(specView.getSpecName());
                    vo.setCheckSpareSpecCode(specView.getSpecCode());
                });
            }
            vo.setStore(storeList.stream().filter(f -> Objects.equals(f.getId(), spare.getStoreId())).map(ZjStore::getName).findFirst().orElse(""));
            return vo;
        }).toList();
    }

    // 审核工单备件
    @Override
    @Transactional
    public void checkOrderSpare(AccounLoginInfo loginInfo, WorkSpareCheckVo workSpareCheckVo) {
        ZjWorkSpare workSpare = workSpareService.getById(workSpareCheckVo.getId());
        Assert.isTrue(null != workSpare, "工单备件ID参数["+ workSpareCheckVo.getId() +"]的工单备件数据不存在");
        Assert.isTrue(workSpare.getStatus() == WorkConstant.WORK_SPARE_STATUS_1, "工单备件单号["+ workSpare.getCode() +"]的备件已审核，不允许重复审核或其他流程操作");
        if (workSpareCheckVo.getReceiptAddrType() == 1) {
            Assert.isTrue(null != userService.getById(workSpareCheckVo.getUserOrNetworkId()), "收货地址类型的工单客户参数["+ workSpareCheckVo.getUserOrNetworkId() +"]的数据不存在系统中");
        }
        if (workSpareCheckVo.getReceiptAddrType() == 2) {
            Assert.isTrue(null != networkService.getById(workSpareCheckVo.getUserOrNetworkId()), "收货地址类型的服务商参数["+ workSpareCheckVo.getUserOrNetworkId() +"]的数据不存在系统中");
        }
        List<WorkSpareMaterialCheckVo> spareMaterials = workSpareCheckVo.getWorkSpareMaterials();
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(spareMaterials.stream().map(WorkSpareMaterialCheckVo::getSpareId).distinct().toList(),
                spareMaterials.stream().map(WorkSpareMaterialCheckVo::getSpecId).distinct().toList());
        // 校验非自购配件的仓库数据
        if (workSpare.getNetworkSpareType() != 3 && spareMaterials.stream().anyMatch(f -> f.getStatus() == 2)) {
            // 获取仓库及仓库商品库存
            List<ViewStoreStoreGoodsStock> viewStoreStoreGoodsStockList = viewStoreStoreGoodsStockService.getByStoreIds(spareMaterials.stream().map(WorkSpareMaterialCheckVo::getStoreId).distinct().toList());
            Assert.notEmpty(viewStoreStoreGoodsStockList, "配件出库的仓库数据不存在");
            // 获取仓位
            List<ZjStorePosition> positionList = storePositionService.getStorePositionNameByIds(spareMaterials.stream().map(WorkSpareMaterialCheckVo::getStorePositionId).distinct().toList());
            ViewGoods viewGoods = null;
            ZjStore store = null;
            ZjStorePosition storePosition = null;
            ViewStoreStoreGoodsStock viewStoreStoreGoodsStock = null;
            for (WorkSpareMaterialCheckVo materialVo : spareMaterials) {
                if (materialVo.getStatus() == 3) {
                    continue;
                }
                viewGoods = viewGoodsList.stream().filter(f -> Objects.equals(2, f.getGoodsType()) && Objects.equals(f.getId(), materialVo.getSpareId()) &&
                        Objects.equals(f.getSpecId(), materialVo.getSpecId())).findFirst().orElse(null);
                Assert.notNull(viewGoods, "配件参数[ " + materialVo.getSpareId() + "、" + materialVo.getSpecId() + " ]的数据不存在，请检查出库配件参数是否正确！");

                store = viewStoreStoreGoodsStockList.stream().filter(f -> Objects.equals(f.getId(), materialVo.getStoreId())).findFirst().orElse(null);
                Assert.notNull(store, "配件型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]出库仓库数据不存在");

                viewStoreStoreGoodsStock = viewStoreStoreGoodsStockList.stream()
                        .filter(f -> Objects.equals(f.getId(), materialVo.getStoreId()) && Objects.equals(f.getStorePositionId(), materialVo.getStorePositionId()))
                        .filter(f -> Objects.equals(2, f.getGoodsType()))
                        .filter(f -> Objects.equals(f.getGoodsId(), materialVo.getSpareId()) && Objects.equals(f.getGoodsSpecId(), materialVo.getSpecId()))
                        .findFirst().orElse(null);
                // 校验是否允许负库存出库
                if (!store.getCanNegativeStock() && (null == viewStoreStoreGoodsStock || viewStoreStoreGoodsStock.getSystemStock() <= 0)) {
                    Assert.isTrue(false, "仓库[ " + store.getName() + " ]不允许负库存出库");
                }
                if (store.getEnableStorePosition()) {
                    Assert.isTrue(null != materialVo.getStorePositionId() && materialVo.getStorePositionId() > 0,
                            "配件型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]的出库仓库[ " + store.getName() + " ]已启用仓位，请必须指定仓库仓位后再审核出库");
                    storePosition = positionList.stream().filter(f -> Objects.equals(f.getId(), materialVo.getStorePositionId())).findFirst().orElse(null);
                    Assert.notNull(storePosition, "配件型号规格[ " + viewGoods.getModel() + " " + viewGoods.getSpecName() + " ]出库仓库仓位的数据不存在");
                    Assert.isTrue(Objects.equals(store.getId(), storePosition.getStoreId()), "出库仓位[ " + storePosition.getName() + " ]不属于仓库[ " + store.getName() + " ]下的仓位");
                }
            }
        }
        // 校验旧件退回的仓库
        if (workSpareCheckVo.getOldCopeWay() == 2) {
            ZjStore store = storeService.getById(workSpareCheckVo.getStoreId());
            Assert.notNull(store, "退回仓库的仓库数据不存在");
            Assert.isFalse(store.getOutStore(), "退回仓库[ "+store.getName()+" ]为外仓库，退回仓库必须指定为内仓，请更改退回仓库后重新提交审核");
            if (store.getEnableStorePosition()) {
                Assert.isTrue(null != workSpareCheckVo.getStorePositionId() && workSpareCheckVo.getStorePositionId() > 0,
                        "退回仓库[ "+store.getName()+" ]已启用仓位，必须指定仓库仓位");
                ZjStorePosition storePosition = storePositionService.getById(workSpareCheckVo.getStorePositionId());
                Assert.notNull(storePosition, "退回仓库[ "+store.getName()+" ]的仓位数据不存在");
                Assert.isTrue(Objects.equals(store.getId(), storePosition.getStoreId()), "仓位[ "+storePosition.getName()+" ]不属于退回仓库[ "+store.getName()+" ]下的数据");
            } else {
                workSpareCheckVo.setStorePositionId(0L);
            }
        }
        QueryWrapper<ZjWorkSpareMaterial> materialQueryWrapper = new QueryWrapper<>();
        materialQueryWrapper.eq("work_spare_id", workSpareCheckVo.getId());
        int count = workSpareMaterialService.count(materialQueryWrapper);
        Assert.isTrue(count == workSpareCheckVo.getWorkSpareMaterials().size(), "审核的工单备件数量与申请的数量不一至，审核时必须全部工单备件数量一并审核");
        Assert.isTrue(workSpareCheckVo.getWorkSpareMaterials().stream().noneMatch(a -> 1 == a.getStatus()), "工单备件存在未审核的备件数据，请审核后重新提交");
        ZjWorkOrder workOrder = workOrderService.getById(workSpare.getWorkId());

        ZjWorkSpare spare = new ZjWorkSpare();
        spare.setId(workSpareCheckVo.getId());
        spare.setOldCopeWay(workSpareCheckVo.getOldCopeWay());
        spare.setReviewTime(new Date());
        spare.setReviewEmpId(loginInfo.getId());
        spare.setReviewEmp(loginInfo.getName());
        spare.setReviewRemark(workSpareCheckVo.getRemark());
        BigDecimal freezePrice = new BigDecimal("0.0");
        WorkLogVo logVo = null;
        if (workSpareCheckVo.getWorkSpareMaterials().stream().allMatch(a -> 2 == a.getStatus()) || workSpareCheckVo.getWorkSpareMaterials().stream().anyMatch(a -> 2 == a.getStatus())) {
            spare.setStatus(WorkConstant.WORK_SPARE_STATUS_2);
            logVo = new WorkLogVo(loginInfo, workSpare.getWorkId(), "审核申请的工单备件", "工单客服【" + loginInfo.getName() + "】已审核工单备件物料，审核结果：已通过；备注："+ workSpareCheckVo.getRemark());
            freezePrice = workSpareCheckVo.getWorkSpareMaterials().stream().filter(f -> f.getStatus() == 2 && f.getType() == 1)
                    .map(WorkSpareMaterialCheckVo::getReceiveFactoryPrice).reduce(BigDecimal::add).orElse(new BigDecimal("0.0"));

        }
        if (workSpareCheckVo.getWorkSpareMaterials().stream().allMatch(a -> 3 == a.getStatus())) {
            spare.setStatus(WorkConstant.WORK_SPARE_STATUS_3);
            logVo = new WorkLogVo(loginInfo, workSpare.getWorkId(), "审核申请的工单备件", "工单客服【" + loginInfo.getName() + "】已审核工单备件物料，审核结果：已驳回；备注：" + workSpareCheckVo.getRemark());
        }
        workSpareService.updateById(spare);

        ZjWorkSpareReceipt receipt = new ZjWorkSpareReceipt();
        BeanUtil.copyProperties(workSpareCheckVo, receipt);
        workSpareReceiptService.updateById(receipt);
        // 审核配件并出库
        checkOrderSpareMaterial(loginInfo, workSpare, workSpareCheckVo);
//        workSpareMaterialService.checkOrderSpareMaterial(loginInfo, workSpare.getWorkId(), workSpareCheckVo.getWorkSpareMaterials());
        ZjWorkSpareReturn spareReturn = workSpareReturnService.save(loginInfo, workSpare.getWorkId(), workSpare.getWorkNo(), workSpare.getCode(), spare.getStatus(), spare.getNetworkId(), workSpareCheckVo);
        // 工单配件旧件入库
        if (null != spareReturn) {
            saveOldSpareInStore(loginInfo, spareReturn, workSpareCheckVo);
        }
        ZjWorkOrder newOrder = new ZjWorkOrder();
        newOrder.setId(workOrder.getId());
        newOrder.setNewAdvance(workOrder.getNewAdvance());
        newOrder.setWaitCopeEvent(workOrder.getWaitCopeEvent() -1);
        workOrderService.updateById(newOrder);
        ZjWorkDetail detail = new ZjWorkDetail();
        detail.setId(workOrder.getId());
        detail.setNoReviewApplyWorkSpareNum(-1);
        workDetailService.updateOrderEventById(detail);
        // 冻结品牌商家费用
        factoryAccountBalanceService.updateFreezePriceById(workOrder.getFactoryId(), freezePrice);
        if (null != logVo) {
            WorkServiceLog.saveService(logVo);
            WorkServiceLog.saveServiceWorkSpareLog(new WorkSpareLogVo(loginInfo, workSpare.getWorkId(), workSpare.getId(), logVo.getEvent(), logVo.getContent()));
        }
    }

    /**
     * 审核工单配件并出库
     * @param loginInfo
     * @param workSpare
     * @param workSpareCheckVo
     */
    public void checkOrderSpareMaterial(AccounLoginInfo loginInfo, ZjWorkSpare workSpare, WorkSpareCheckVo workSpareCheckVo) {
        List<WorkSpareMaterialCheckVo> workSpareMaterials = workSpareCheckVo.getWorkSpareMaterials();
        if (CollectionUtil.isEmpty(workSpareMaterials)) {
            return;
        }
        List<Long> ids = workSpareMaterials.stream().map(WorkSpareMaterialCheckVo::getId).toList();
        List<ZjWorkSpareMaterial> materialList = workSpareMaterialService.listByIds(ids);
        List<String> ids2 = ids.stream().filter(f -> materialList.stream().noneMatch(fm -> Objects.equals(fm.getId(), f))).map(String::valueOf).toList();
        Assert.isTrue(CollectionUtil.isEmpty(ids2), "审核的工单备件物料信息ID参数["+ String.join("、", ids2) +"]的数据不存在");

        List<ZjWorkSpareMaterial> updates = new ArrayList<>();
        List<ZjWorkSpareMaterialAnnex> annexes = new ArrayList<>();
        List<Long> delImages = new ArrayList<>();
        ZjWorkSpareMaterial material = null;
        ZjWorkSpareMaterialAnnex annex = null;

        List<StoreOutServiceGoodsVo> storeOutServiceGoodsVos = null;
        if (workSpare.getType() == 2 && (workSpare.getNetworkSpareType() == 1 || workSpare.getNetworkSpareType() == 2)) {
            storeOutServiceGoodsVos = new ArrayList<>();
        }

        for (WorkSpareMaterialCheckVo vo : workSpareMaterials) {
            material = new ZjWorkSpareMaterial();
            BeanUtil.copyProperties(vo, material);
            updates.add(material);
            if (CollectionUtil.isNotEmpty(vo.getImages())) {
                for (OrderImageVo image : vo.getImages()) {
                    if (null == image.getId()) {
                        annex = new ZjWorkSpareMaterialAnnex();
                        annex.setId(IdWorker.getId());
                        annex.setCustAccId(loginInfo.getCustAccId());
                        annex.setWorkId(workSpare.getWorkId());
                        annex.setWorkSpareMaterialId(material.getId());
                        annex.setImage(image.getImage());
                        annexes.add(annex);
                    }
                }
            }
            if (CollectionUtil.isNotEmpty(vo.getDelImageIds())) {
                delImages.addAll(vo.getDelImageIds());
            }
            // 外部工程师、服务商仓库物料出库
            if (vo.getStatus() == 2 && null != storeOutServiceGoodsVos) {
                storeOutServiceGoodsVos.add(new StoreOutServiceGoodsVo(vo.getStoreId(), 2, vo.getSpareId(), vo.getSpecId(), (long)vo.getQty()));
            }
        }
        workSpareMaterialService.updateBatchById(updates);
        if (CollectionUtil.isNotEmpty(annexes)) workSpareMaterialAnnexService.saveBatch(annexes);
        if (CollectionUtil.isNotEmpty(delImages)) workSpareMaterialAnnexService.removeByIds(delImages);
        if (workSpare.getType() == 1) {
            saveSpareOutStore(loginInfo, workSpare, workSpareCheckVo);
        }
        // 外部仓库出库后，对应仓库商品数量要减少
        conStoreOutboundService.storeOutServiceGoods(loginInfo.getCustAccId(), true, storeOutServiceGoodsVos);
    }

    /**
     * 保存工单配件出库单
     * @param loginInfo
     * @param workSpare
     * @param workSpareCheckVo
     */
    private void saveSpareOutStore(AccounLoginInfo loginInfo, ZjWorkSpare workSpare, WorkSpareCheckVo workSpareCheckVo) {
        List<WorkSpareMaterialCheckVo> spareMaterials = workSpareCheckVo.getWorkSpareMaterials().stream().filter(f -> f.getStatus() == 2).toList();
        if (CollectionUtil.isEmpty(spareMaterials)) {
            return;
        }
        StoreOutboundVo outboundVo = new StoreOutboundVo();
        outboundVo.setTypeId(storeTypeService.getOutStoreOrderSpareTypeIdByCustAccId(loginInfo.getCustAccId()));
        outboundVo.setStoreType(Objects.equals(1, workSpare.getType())? 0 : workSpare.getNetworkSpareType());
        outboundVo.setSource(2);
        outboundVo.setRemark(workSpare.getApplyRemark());
        outboundVo.setReviewRemark(workSpareCheckVo.getRemark());
        outboundVo.setCreateTime(new Date());

        StoreOutboundReceiptVo receiptVo = new StoreOutboundReceiptVo();
        receiptVo.setReceiptAddrType(workSpareCheckVo.getReceiptAddrType() == 1? StoreConstant.STORE_OUT_RECEIPTS_TYPE_1 :  StoreConstant.STORE_OUT_RECEIPTS_TYPE_2);
        receiptVo.setRelationId(workSpareCheckVo.getReceiptAddrType() == 1? workSpareCheckVo.getUserOrNetworkId() : 0L);
        receiptVo.setStorePositionId(0L);
        receiptVo.setReceiptName(workSpareCheckVo.getReceiptName());
        receiptVo.setReceiptPhone(workSpareCheckVo.getReceiptPhone());
        receiptVo.setReceiptProvince(workSpareCheckVo.getReceiptProvince());
        receiptVo.setReceiptCity(workSpareCheckVo.getReceiptCity());
        receiptVo.setReceiptArea(workSpareCheckVo.getReceiptArea());
        receiptVo.setReceiptTown(workSpareCheckVo.getReceiptTown());
        receiptVo.setReceiptAddress(workSpareCheckVo.getReceiptAddress());
        outboundVo.setReceiptVo(receiptVo);

        List<StoreBoundMaterialVo> outBoundMaterialVos = new ArrayList<>();
        StoreBoundMaterialVo materialVo = null;
        for (WorkSpareMaterialCheckVo material : spareMaterials) {
            materialVo = new StoreBoundMaterialVo();
            materialVo.setType(2);
            materialVo.setStoreId(material.getStoreId());
            materialVo.setStorePositionId(material.getStorePositionId());
            materialVo.setGoodsId(material.getSpareId());
            materialVo.setGoodsSpecId(material.getSpecId());
            materialVo.setPrice(material.getPrice());
            materialVo.setQty(material.getQty());
            materialVo.setRemark(StringUtils.isNotBlank(material.getRemark())? material.getRemark() : "");
            outBoundMaterialVos.add(materialVo);
        }
        outboundVo.setOutBoundMaterialVos(outBoundMaterialVos);
        ZjStoreOutboundOrderSpare outboundOrderSpare = new ZjStoreOutboundOrderSpare();
        outboundOrderSpare.setId(IdWorker.getId());
        outboundOrderSpare.setCustAccId(loginInfo.getCustAccId());
        outboundOrderSpare.setWorkId(workSpare.getWorkId());
        outboundOrderSpare.setWorkSpareId(workSpare.getId());
        outboundOrderSpare.setWorkSpareNo(workSpare.getCode());
        conStoreOutboundService.saveOrCheck(loginInfo, "2", outboundOrderSpare, outboundVo);
    }


    /**
     * 保存工单配件旧件入库
     * @param loginInfo
     * @param spareReturn
     * @param workSpareCheckVo
     */
    private void saveOldSpareInStore(AccounLoginInfo loginInfo, ZjWorkSpareReturn spareReturn, WorkSpareCheckVo workSpareCheckVo) {
        StoreInboundVo inboundVo = new StoreInboundVo();
        inboundVo.setTypeId(storeTypeService.getInStoreOrderSpareTypeIdByCustAccId(loginInfo.getCustAccId()));
        inboundVo.setStoreType(0);
        inboundVo.setSource(2);
        inboundVo.setRemark("工单配件旧件退回仓库");
        inboundVo.setReviewRemark(StringUtils.isNotBlank(workSpareCheckVo.getRemark())? workSpareCheckVo.getRemark() : "");
        inboundVo.setInboundMaterialVos(workSpareCheckVo.getWorkSpareMaterials().stream().map(spare -> {
            StoreBoundMaterialVo materialVo = new StoreBoundMaterialVo();
            materialVo.setType(2);
            materialVo.setStoreId(spareReturn.getStoreId());
            materialVo.setStorePositionId(spareReturn.getStorePositionId());
            materialVo.setGoodsId(spare.getSpareId());
            materialVo.setGoodsSpecId(spare.getSpecId());
            materialVo.setPrice(spare.getPrice());
            materialVo.setQty(spare.getQty());
            materialVo.setRemark(spare.getRemark());
            return materialVo;
        }).toList());
        ZjStoreInboundOrderSpare inboundOrderSpare = new ZjStoreInboundOrderSpare();
        inboundOrderSpare.setId(IdWorker.getId());
        inboundOrderSpare.setCustAccId(loginInfo.getCustAccId());
        inboundOrderSpare.setWorkId(spareReturn.getWorkId());
        inboundOrderSpare.setWorkSpareReturnId(spareReturn.getId());
        inboundOrderSpare.setWorkSpareReturnNo(spareReturn.getCode());
        conStoreInboundService.save(loginInfo, "2", inboundOrderSpare, inboundVo);
    }

    // 获取服务商详情之工单配件列表
    @Override
    public Map<String, Object> getNetworkDetailOrderSpareList(Long networkId, PageUtil pageUtil) {
        PageUtil.setPageLimit(pageUtil);
        long count = workSpareService.getNetworkDetailOrderSpareListCount(networkId);
        if (count <= 0) {
            return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, new ArrayList<>());
        }
        List<ZjWorkSpare> workSpareList = workSpareService.getNetworkDetailOrderSpareList(networkId, pageUtil);
        return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, getSpareListVos(workSpareList));
    }

    // 获取商家详情之工单配件列表
    @Override
    public Map<String, Object> getFactoryDetailOrderSpareList(Long factoryId, PageUtil pageUtil) {
        PageUtil.setPageLimit(pageUtil);
        long count = workSpareService.getFactoryDetailOrderSpareListCount(factoryId);
        if (count <= 0) {
            return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, new ArrayList<>());
        }
        List<ZjWorkSpare> workSpareList = workSpareService.getFactoryDetailOrderSpareList(factoryId, pageUtil);
        return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, getSpareListVos(workSpareList));
    }

    private List<WorkSpareListVo> getSpareListVos(List<ZjWorkSpare> workSpareList) {
        List<Long> workSpareIds = workSpareList.stream().map(ZjWorkSpare::getId).toList();
        List<ZjWorkSpareMaterial> spareMaterialList = workSpareMaterialService.getByWorkSpareIds(workSpareIds);
        List<Long> spareIds = spareMaterialList.stream().filter(f -> null != f.getSpareId() && 0 != f.getSpareId()).map(ZjWorkSpareMaterial::getSpareId).distinct().toList();
        List<Long> spareSpecIds = spareMaterialList.stream().filter(f -> null != f.getSpecId() && 0 != f.getSpecId()).map(ZjWorkSpareMaterial::getSpecId).distinct().toList();
        List<ViewGoods> viewGoodsList = viewGoodsService.getByGoodsIdsAndGoodsSpecIds(spareIds, spareSpecIds);
        List<Long> ids = spareMaterialList.stream().map(ZjWorkSpareMaterial::getId).toList();
        List<ZjWorkSpareMaterialApply> materialApplyList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(ids)) {
            materialApplyList.addAll(workSpareMaterialApplyService.listByIds(ids));
        }
        // 获取发货仓库
        List<ZjStore> storeList = new ArrayList<>();
        List<Long> storeIds = spareMaterialList.stream().filter(f -> null != f.getStoreId() && f.getStoreId() > 0).map(ZjWorkSpareMaterial::getStoreId).distinct().toList();
        if (CollectionUtil.isNotEmpty(storeIds)) {
            storeList.addAll(storeService.getStoreNameByIds(storeIds));
        }
        return workSpareList.stream().map(spare -> {
            OrderDetailWorkSpareListVo spareListVo = getSpareListVo(spareMaterialList, viewGoodsList, materialApplyList, spare);
            WorkSpareListVo vo = new WorkSpareListVo();
            BeanUtil.copyProperties(spareListVo, vo);
            vo.setWorkId(spare.getWorkId());
            vo.setWorkNo(spare.getWorkNo());
            vo.setStore(storeList.stream().filter(f -> spareMaterialList.stream().anyMatch(f1 ->
                    Objects.equals(f1.getWorkSpareId(), spare.getId()) && Objects.equals(f1.getStoreId(), f.getId()))).map(ZjStore::getName).collect(Collectors.joining("、")));
            return vo;
        }).toList();
    }

    private static OrderDetailWorkSpareListVo getSpareListVo(List<ZjWorkSpareMaterial> spareMaterialList, List<ViewGoods> viewGoodsList, List<ZjWorkSpareMaterialApply> materialApplyList, ZjWorkSpare spare) {
        OrderDetailWorkSpareListVo vo = new OrderDetailWorkSpareListVo();
        BeanUtil.copyProperties(spare, vo);
        vo.setType(WorkConverter.getWorkSpareApplyType(spare.getType(), spare.getNetworkSpareType()));
        vo.setApplyEmp("【" + (spare.getApplyEmpType() == 1? "系统客服" : spare.getApplyEmpType() == 2? "服务商移动端" : "第三方系统") + "】" + spare.getApplyEmp());
        vo.setCreateTime(spare.getGmtCreate());
        vo.setUpdateTime(spare.getGmtUpdate());
        List<ZjWorkSpareMaterial> materials = spareMaterialList.stream().filter(f -> Objects.equals(f.getWorkSpareId(), spare.getId())).toList();
        vo.setTotalPrice(materials.stream().filter(f -> f.getStatus() == 2).map(fee -> {
            return fee.getPrice().multiply(new BigDecimal(fee.getQty()));
        }).reduce(new BigDecimal("0.0"), BigDecimal::add));
        vo.setPayNetworkTotalPrice(materials.stream().filter(f -> f.getStatus() == 2).map(fee -> {
            return fee.getPayNetworkPrice().multiply(new BigDecimal(fee.getQty()));
        }).reduce(new BigDecimal("0.0"), BigDecimal::add));
        vo.setReceiveFactoryTotalPrice(materials.stream().filter(f -> f.getStatus() == 2).map(fee -> {
            return fee.getReceiveFactoryPrice().multiply(new BigDecimal(fee.getQty()));
        }).reduce(new BigDecimal("0.0"), BigDecimal::add));
        StringBuilder builder = new StringBuilder();
        materials.forEach(t -> {
            if (0 == t.getSpareId()) {
                ZjWorkSpareMaterialApply apply = materialApplyList.stream().filter(f -> Objects.equals(f.getId(), t.getId())).findFirst().orElse(null);
                if (null != apply) {
                    builder.append(apply.getModel()).append("、").append(apply.getSpec()).append("；");
                }
            } else {
                viewGoodsList.stream().filter(f -> Objects.equals(f.getId(), t.getSpareId()) && Objects.equals(f.getSpecId(), t.getSpecId())).findFirst().ifPresent(specView -> {
                    builder.append(specView.getModel()).append("、").append(specView.getSpecName()).append("；");
                });
            }
        });
        vo.setModel(builder.toString());
        builder.delete(0, builder.length());
        return vo;
    }


}
